package network.tcp.nio;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @program: bio
 * @description:
 * @author: zhanghz001
 * @create: 2020-10-27 15:48
 **/
public class NioServer2 {
    public static void main(String[] args) {
        //首先是一个nio的server
        // 需要默写nio服务器
        server();
    }

    private static void server() {
        try (ServerSocketChannel channel = ServerSocketChannel.open();) {

            //创建channel
            SocketAddress local = new InetSocketAddress(10000);
            // channel.bind(local);

            //绑定
            channel.bind(local);

            //设置非阻塞
            channel.configureBlocking(false);

            //绑定通道
            Selector selector = Selector.open();

            //注册选择器,和选择器类型
            channel.register(selector, SelectionKey.OP_ACCEPT);

            //设置了非
            while (true) {
                // System.out.println("外层循环中");
                //判断是否有客户端连接
                int select = selector.select();
                // System.out.println("2222");
                if (select > 0) {
                    System.out.println("有客户端连接");
                    //循环,修改状态,
                    //会遍历所有的服务端通道.看谁准备好了,谁准备好了,就让谁去连接
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
                    while (selectionKeyIterator.hasNext()) {
                        //获取令牌,进行循环
                        SelectionKey selectionKey = selectionKeyIterator.next();
                        //如果是只读的,就改成改改状态
                        if (selectionKey.isAcceptable()) {
                            //修改channel,可用后就进行通信
                            System.out.println("===isAcceptable===");

                            ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                            // ssc.configureBlocking(false);

                            //
                            SocketChannel accept = ssc.accept();
                            accept.configureBlocking(false);
                            //注册
                            accept.register(selector, SelectionKey.OP_READ);
                            //当客户端来连接的时候,所有操作都全部执行完毕

                            // 不要释放资源 因为还没有用,只是改了状态
                            // accept.close();
                            // ssc.close();
                        } else if (selectionKey.isReadable()) {
                            System.out.println("===isReadable===");

                            //得到可用的channel,进行通信
                            try (SocketChannel client = (SocketChannel) selectionKey.channel();) {
                                if (client != null) {

                                    ByteBuffer dst = ByteBuffer.allocate(1024);
                                    int len;
                                    while ((len = client.read(dst)) > 0) {
                                        dst.flip();
                                        System.out.println(new String(dst.array(), 0, len));
                                        dst.clear();
                                    }

                                    //
                                    ByteBuffer src = ByteBuffer.wrap("服务器响应数据了".getBytes());
                                    client.write(src);
                                    // client.shutdownOutput();
                                    //
                                }
                                //设置非阻塞
                                //
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                // 释放资源   加入到 try的小括号中

                            }
                        }
                        selectionKeyIterator.remove();
                    }

                }
                System.out.println("=========外层循环一次========");
            }
            //    循环获取连接

            //获取接口的信息,

            //读取到消息

            //释放资源   加入到 try的小括号中
            // channel.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
}
